package ws

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

const (
	// WebSocket配置
	WriteWait      = 10 * time.Second
	PongWait       = 60 * time.Second
	PingPeriod     = (PongWait * 9) / 10
	MaxMessageSize = 512 * 1024
)

// WebSocket升级器
var Upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有来源
	},
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

// JSON-RPC消息结构
type JSONRPCRequest struct {
	JSONRPC string      `json:"jsonrpc"`
	ID      int         `json:"id"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params"`
}

type JSONRPCResponse struct {
	JSONRPC string      `json:"jsonrpc"`
	ID      int         `json:"id,omitempty"`
	Method  string      `json:"method,omitempty"`
	Result  interface{} `json:"result,omitempty"`
	Params  interface{} `json:"params,omitempty"`
}

// 开始会话参数
type StartParams struct {
	UUID     string `json:"uuid"`
	Username string `json:"username"`
	Rate     int    `json:"rate"`
	Codec    string `json:"codec"`
	MS       int    `json:"ms"`
	Audio    string `json:"audio"`
}

// 响应结果
type StartResult struct {
	Code      int    `json:"code"`
	Message   string `json:"message"`
	Audio     string `json:"audio"`
	Heartbeat int    `json:"heartbeat"`
}

// 文本识别结果参数
type TextParams struct {
	Confidence float64 `json:"confidence"`
	Text       string  `json:"text"`
	SessionID  string  `json:"session_id"`
}

// Pong参数
type PongParams struct {
	SessionID string `json:"session_id"`
	Timestamp int64  `json:"timestamp"`
}

// 消息类型
const (
	MessageTypeJSON   = "json"
	MessageTypeBinary = "binary"
)

// 消息结构
type Message struct {
	Type    string
	Content []byte
}

// 用户会话管理
type UserSession struct {
	Conn            *websocket.Conn
	SessionID       string
	UUID            string
	Username        string
	RecvPackets     int64
	SendPackets     int64
	AudioParams     StartParams
	IsActive        bool
	LastActivity    time.Time
	HeartbeatTicker *time.Ticker
	Send            chan *Message
	Hub             *Hub
}

// 会话管理中心
type Hub struct {
	Sessions   map[string]*UserSession
	Register   chan *UserSession
	Unregister chan *UserSession
	Mutex      sync.RWMutex
	Counter    int64
}

// 创建新的Hub
func NewHub() *Hub {
	return &Hub{
		Sessions:   make(map[string]*UserSession),
		Register:   make(chan *UserSession),
		Unregister: make(chan *UserSession),
		Counter:    0,
	}
}

// Hub运行
func (h *Hub) Run() {
	for {
		select {
		case session := <-h.Register:
			h.Mutex.Lock()
			// 注册新会话
			h.Sessions[session.SessionID] = session
			h.Mutex.Unlock()
			log.Printf("会话[%s]注册，连接地址: %s", session.SessionID, session.Conn.RemoteAddr().String())

		case session := <-h.Unregister:
			h.Mutex.Lock()
			if _, ok := h.Sessions[session.SessionID]; ok {
				delete(h.Sessions, session.SessionID)
				// 关闭该会话的发送通道
				close(session.Send)
				log.Printf("会话[%s]注销，连接地址: %s，总包数: 接收=%d, 发送=%d",
					session.SessionID, session.Conn.RemoteAddr().String(), session.RecvPackets, session.SendPackets)
			}
			h.Mutex.Unlock()
		}
	}
}

// 获取所有会话状态
func (h *Hub) GetSessionsStatus() map[string]interface{} {
	h.Mutex.RLock()
	defer h.Mutex.RUnlock()

	status := make(map[string]interface{})
	status["total_sessions"] = len(h.Sessions)
	status["sessions"] = make([]map[string]interface{}, 0, len(h.Sessions))

	for _, session := range h.Sessions {
		sessionInfo := map[string]interface{}{
			"session_id":    session.SessionID,
			"username":      session.Username,
			"uuid":          session.UUID,
			"recv_packets":  session.RecvPackets,
			"send_packets":  session.SendPackets,
			"is_active":     session.IsActive,
			"last_activity": session.LastActivity.Format(time.RFC3339),
			"audio_params":  session.AudioParams,
		}
		status["sessions"] = append(status["sessions"].([]map[string]interface{}), sessionInfo)
	}

	return status
}

// 创建新的用户会话
func NewUserSession(conn *websocket.Conn, sessionID string, hub *Hub) *UserSession {
	return &UserSession{
		Conn:         conn,
		SessionID:    sessionID,
		IsActive:     true,
		LastActivity: time.Now(),
		Send:         make(chan *Message, 256),
		Hub:          hub,
	}
}

// 处理开始消息
func (s *UserSession) handleStart(rpc JSONRPCRequest) {
	// 记录接收到的start消息
	log.Printf("会话[%s]接收到start消息: %+v", s.SessionID, rpc)

	// 解析参数
	paramsBytes, _ := json.Marshal(rpc.Params)
	var params StartParams
	if err := json.Unmarshal(paramsBytes, &params); err != nil {
		log.Printf("会话[%s] 解析start参数失败: %v", s.SessionID, err)
		return
	}

	// 设置默认值
	if params.UUID == "" {
		params.UUID = s.SessionID
	}
	if params.Username == "" {
		params.Username = "anonymous"
	}
	if params.Rate == 0 {
		params.Rate = 8000
	}
	if params.Codec == "" {
		params.Codec = "L16"
	}
	if params.MS == 0 {
		params.MS = 100
	}
	if params.Audio == "" {
		params.Audio = "sendrecv"
	}

	s.UUID = params.UUID
	s.Username = params.Username
	s.AudioParams = params

	// 注册会话到Hub（此时用户名已设置）
	s.Hub.Register <- s

	log.Printf("用户[%s][%s]开始会话，UUID: %s", s.SessionID, s.Username, s.UUID)

	// 发送响应
	response := JSONRPCResponse{
		JSONRPC: "2.0",
		ID:      rpc.ID,
		Result: StartResult{
			Code:      200,
			Message:   "OK",
			Audio:     params.Audio,
			Heartbeat: 10,
		},
	}

	// 记录发送的响应
	jsonData, _ := json.Marshal(response)
	log.Printf("用户[%s][%s]发送start响应: %s", s.SessionID, s.Username, string(jsonData))

	s.sendJSON(response)

	// 启动心跳
	s.startHeartbeat()
}

// 处理音频数据
func (s *UserSession) handleAudioData(data []byte) {
	s.RecvPackets++
	s.LastActivity = time.Now()

	// 记录接收到的音频数据
	log.Printf("用户[%s][%s]接收到音频数据，包大小: %d bytes，包序号: %d", s.SessionID, s.Username, len(data), s.RecvPackets)

	// 回显音频数据
	s.sendBinary(data)

	// 模拟ASR识别结果（每20个包返回一次）
	if s.RecvPackets%20 == 0 {
		response := JSONRPCResponse{
			JSONRPC: "2.0",
			Method:  "text",
			Params: TextParams{
				Confidence: 0.99,
				Text:       fmt.Sprintf("用户%s说：你好 (包%d)", s.Username, s.RecvPackets),
				SessionID:  s.SessionID,
			},
		}

		// 记录发送的文本识别结果
		log.Printf("用户[%s][%s]发送文本识别结果: %+v", s.SessionID, s.Username, response)

		s.sendJSON(response)
	}
}

// 处理心跳
func (s *UserSession) handlePing() {
	s.LastActivity = time.Now()

	// 记录接收到的心跳
	log.Printf("用户[%s][%s]接收到ping心跳", s.SessionID, s.Username)

	response := JSONRPCResponse{
		JSONRPC: "2.0",
		Method:  "pong",
		Params: PongParams{
			SessionID: s.SessionID,
			Timestamp: time.Now().UnixMilli(),
		},
	}

	// 记录发送的pong响应
	log.Printf("用户[%s][%s]发送pong响应: %+v", s.SessionID, s.Username, response)

	s.sendJSON(response)
}

// 处理停止
func (s *UserSession) handleStop() {
	log.Printf("用户[%s][%s]接收到stop消息，停止会话", s.SessionID, s.Username)
	s.IsActive = false
	s.stopHeartbeat()
}

// 启动心跳
func (s *UserSession) startHeartbeat() {
	s.HeartbeatTicker = time.NewTicker(30 * time.Second)
	go func() {
		for range s.HeartbeatTicker.C {
			if !s.IsActive {
				break
			}
			// 发送心跳
			response := JSONRPCResponse{
				JSONRPC: "2.0",
				Method:  "ping",
				Params: PongParams{
					SessionID: s.SessionID,
					Timestamp: time.Now().UnixMilli(),
				},
			}

			// 记录发送的心跳
			log.Printf("用户[%s][%s]发送ping心跳: %+v", s.SessionID, s.Username, response)

			s.sendJSON(response)
		}
	}()
}

// 停止心跳
func (s *UserSession) stopHeartbeat() {
	if s.HeartbeatTicker != nil {
		s.HeartbeatTicker.Stop()
	}
}

// 发送JSON消息
func (s *UserSession) sendJSON(data interface{}) {
	jsonData, err := json.Marshal(data)
	if err != nil {
		log.Printf("用户[%s][%s]JSON序列化失败: %v", s.SessionID, s.Username, err)
		return
	}

	// 记录JSON消息发送
	log.Printf("用户[%s][%s]发送JSON消息，大小: %d bytes", s.SessionID, s.Username, len(jsonData))

	// 创建带类型的消息
	msg := &Message{
		Type:    MessageTypeJSON,
		Content: jsonData,
	}

	select {
	case s.Send <- msg:
	default:
		log.Printf("用户[%s][%s]发送缓冲区满，关闭连接", s.SessionID, s.Username)
		s.close()
	}
}

// 发送二进制数据
func (s *UserSession) sendBinary(data []byte) {
	// 记录二进制消息发送
	log.Printf("用户[%s][%s]发送二进制消息，大小: %d bytes", s.SessionID, s.Username, len(data))

	// 创建带类型的消息
	msg := &Message{
		Type:    MessageTypeBinary,
		Content: data,
	}

	select {
	case s.Send <- msg:
	default:
		log.Printf("用户[%s][%s]发送缓冲区满，关闭连接", s.SessionID, s.Username)
		s.close()
	}
}

// 关闭连接
func (s *UserSession) close() {
	s.IsActive = false
	s.Conn.Close()
	s.Hub.Unregister <- s
}

// 读取消息
func (s *UserSession) ReadPump() {
	defer func() {
		s.close()
	}()

	s.Conn.SetReadLimit(MaxMessageSize)
	s.Conn.SetReadDeadline(time.Now().Add(PongWait))
	s.Conn.SetPongHandler(func(string) error {
		s.Conn.SetReadDeadline(time.Now().Add(PongWait))
		return nil
	})

	for {
		messageType, message, err := s.Conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("用户[%s][%s] WebSocket错误: %v", s.SessionID, s.Username, err)
			}
			break
		}

		// 记录接收到的消息类型和长度
		var typeStr string
		switch messageType {
		case websocket.TextMessage:
			typeStr = "text"
		case websocket.BinaryMessage:
			typeStr = "binary"
		default:
			typeStr = "unknown"
		}
		log.Printf("用户[%s][%s]接收到%s消息，长度: %d bytes", s.SessionID, s.Username, typeStr, len(message))

		// 根据消息类型处理
		if messageType == websocket.TextMessage {
			// 文本消息，尝试解析为JSON-RPC
			var rpc JSONRPCRequest
			if err := json.Unmarshal(message, &rpc); err != nil {
				log.Printf("用户[%s][%s]JSON解析失败: %v", s.SessionID, s.Username, err)
				continue
			}

			// 记录解析后的RPC消息
			log.Printf("用户[%s][%s]解析RPC消息: 方法=%s, ID=%d", s.SessionID, s.Username, rpc.Method, rpc.ID)

			// 根据方法处理消息
			switch rpc.Method {
			case "start":
				s.handleStart(rpc)
			case "ping":
				s.handlePing()
			case "stop":
				s.handleStop()
			default:
				log.Printf("用户[%s][%s]未知方法: %s", s.SessionID, s.Username, rpc.Method)
			}
		} else if messageType == websocket.BinaryMessage {
			// 二进制消息，作为音频数据处理
			s.handleAudioData(message)
		}
	}
}

// 写入消息
func (s *UserSession) WritePump() {
	ticker := time.NewTicker(PingPeriod)
	defer func() {
		ticker.Stop()
		s.Conn.Close()
	}()

	for {
		select {
		case message, ok := <-s.Send:
			s.Conn.SetWriteDeadline(time.Now().Add(WriteWait))
			if !ok {
				s.Conn.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			// 根据消息类型选择发送方式
			var messageType int
			if message.Type == MessageTypeJSON {
				messageType = websocket.TextMessage
			} else {
				messageType = websocket.BinaryMessage
			}

			// 记录发送的消息
			log.Printf("用户[%s][%s]发送消息，类型: %s, 大小: %d bytes", s.SessionID, s.Username, message.Type, len(message.Content))

			w, err := s.Conn.NextWriter(messageType)
			if err != nil {
				return
			}
			w.Write(message.Content)

			if err := w.Close(); err != nil {
				log.Printf("用户[%s][%s]写入消息失败: %v", s.SessionID, s.Username, err)
				return
			}
		case <-ticker.C:
			s.Conn.SetWriteDeadline(time.Now().Add(WriteWait))
			if err := s.Conn.WriteMessage(websocket.PingMessage, nil); err != nil {
				return
			}
		}
	}
}
